/*
socket 工具函数。
**/

#ifndef _SOCKFUNC_INCLUDED_
#define _SOCKFUNC_INCLUDED_
#include <sys/socket.h>
#include <netdb.h>

// not thread safe
const char* sock_ntop(const struct sockaddr *sa, socklen_t len);

// readn writen readline_slow readline_buffer for blocking fd.
// 返回成功读取或者写入的字节数，返回 -1 表示出现错误，若返回的读取的字节数小于 nbytes 表示连接已经断开。
ssize_t readn(int fd, void *buf, size_t nbytes);
ssize_t Readn(int fd, void *buf, size_t nbytes);
ssize_t writen(int fd, const void *buf, size_t nbytes);
ssize_t Writen(int fd, const void *buf, size_t nbytes);

// readline 会把 '\n' 替换成 0 所以最多可以返回 maxbytes-1 有效字节。
// readline 每次处理一行文本数据，若返回 0 表示连接已经断开。
// slow version
ssize_t readline_slow(int fd, void *buf, size_t maxbytes);
// with buffer, not thread safe and must'n mix with other read funcion
ssize_t readline_buffer(int fd, void *buf, size_t maxbytes);
ssize_t Readline_buffer(int fd, void *buf, size_t maxbytes);

// 获取套接字 fd 的地址族，不需要建立连接。
int sockfd_to_family(int fd);

#define readline readline_buffer
#define Readline Readline_buffer

// 直接调用 getaddrinfo 函数而无需指定 hints 结构。返回值需要显示释放掉。
struct addrinfo* host_serv(const char *host, const char *service, int family, int socktype);
int tcp_connect(const char *host, const char *service);
int tcp_listen(const char *host, const char *service, int *addrlenp);
// saptr 需要显示被释放。
int udp_client(const char *host, const char *service, struct sockaddr **saptr, socklen_t *lenptr);
int udp_connect(const char *host, const char *service);
int udp_server(const char *host, const char *service, socklen_t *lenptr);

#endif // _SOCKFUNC_INCLUDED_
